<?php
/**
 * Ecga数据表输出接口集
 *
 * PHP Version 5
 *
 * @package    Ecga
 * @subpackage Models
 * @author     v.k <none@none.com>
 * @copyright  2010 Xingchangxinda Inc.
 * @version    SVN:$Id$
 */
namespace Project\Apps\Ecga\Models\Table;

use \Project\Apps\Ecga\Application;

/**
 * Ecga数据表输出接口工厂类
 *
 * @package   Ecga
 * @author    v.k <none@none.com>
 * @copyright 2010 Xingchangxinda Inc.
 * @version   Release: v0.1
 */
class TableOutputer
{
    
    const EXCEL = 'excel';
    
    /**
     * DOD表输出对象配置
     *
     * @var array
     */
    protected static $tableOutputConfigs = array(
        self::EXCEL => array(
            'ProductSales' => 'ProductSalesExcelOutputer'
        )
    ); 
    
    /**
     * 创建输出对象
     *
     * @param string $type  输出类型
     * @param string $table DOD表
     * 
     * @return IOutputer
     */
    public static function create($type, $table)
    {
        
        $ref = new \ReflectionClass($table);
        
        $className = $ref->getShortName();
        
        if (isset(self::$tableOutputConfigs[$type][$className])) {
            $klass = sprintf(
                '%s\\%s', __NAMESPACE__, 
                self::$tableOutputConfigs[$type][$className]
            );
        } else {
            $klass = sprintf('%s\\%sOutputer', __NAMESPACE__, ucfirst($type));
        }
        $outputer = new $klass;
        $outputer->attachTable($table);
        
        return $outputer;
    }
}

/**
 * DOD表输出接口
 *
 * @package   Ecga
 * @author    v.k <none@none.com>
 * @copyright 2010 Xingchangxinda Inc.
 * @version   Release: v0.1
 */
interface IOutputer
{
    /**
     * 附加数据表
     *
     * @param EcgaTable $table 数据表
     * 
     * @return void
     */
    public function attachTable($table);
    
    /**
     * 输出表
     *
     * @return void
     */
    public function output();
}

/**
 * Ecga表Excel输出类
 *
 * @package   Ecga
 * @author    v.k <none@none.com>
 * @copyright 2010 Xingchangxinda Inc.
 * @version   Release: v0.1
 */
class ExcelOutputer implements IOutputer
{
    /**
     * DOD表对象
     * 
     * @var EcgaTable
     */
    protected $table = null;
    
    /**
     * Excel操作对象
     *
     * @var PHPExcel
     */
    protected $excel = null;

    private $_letters = array();
    
    /**
     * 构造
     *
     * @return void
     */
    public function __construct()
    {
        include_once Application::getInstance()->getPath() . '/library/phpexcel/PHPExcel.php';
        $this->excel = new \PHPExcel();
        for ($i = 0; $i <= 25; $i++) {
            $this->_letters[] = chr(ord('A') + $i);
        }
    }
    
    /**
     * 附加数据表
     *
     * @param EcgaTable $table 数据表
     * 
     * @return void
     */
    public function attachTable($table)
    {
        $this->table = $table;
    }
    
    /**
     * 设置表头
     *
     * @return void
     */
    protected function setHeaders()
    {
        $this->excel->getProperties()->setTitle($this->table->name);
        $this->excel->getProperties()->setSubject($this->table->name);
        $this->excel->getProperties()->setDescription($this->table->name);
        
        $this->excel->setActiveSheetIndex(0);
        $sheet = $this->excel->getActiveSheet();
        
        $lastCell = 0;
        
        // 输出表头组
        foreach ($this->table->headerGroups as $group => $headers) {
            
            $headerCount = count($headers) - 1;
            
            $targetCell = $lastCell + $headerCount;

            $sheet->mergeCells(
                $mergedCells = sprintf(
                    '%s1:%s1', $this->_getCellTag($lastCell), $this->_getCellTag($targetCell)
                )
            );
            $style = $sheet->getStyle($mergedCells);
            
            $style->getAlignment()->setHorizontal(
                \PHPExcel_Style_Alignment::HORIZONTAL_CENTER
            );
            
            $sheet->setCellValue(sprintf('%s1', $this->_getCellTag($lastCell)), $group);
            
            $lastCell = $targetCell + 1;
            
        }
        
        // 输出表头
        $index = 0;
        foreach ($this->table->headers as $id => $caption) {
            
            $cellPos = sprintf('%s2', $this->_getCellTag($index++));
            $sheet->setCellValue($cellPos, $caption['name']);
            
        }
    }
    
    
    /**
     * 输出表内容
     *
     * @return void
     */
    protected function setContents()
    {
        $sheet = $this->excel->getActiveSheet();
        
        $startLine = 2; // headerGroups + headers
        foreach ($this->table->rows as $row) {
            
            $index = 0;
            $startLine++;
            
            foreach ($this->table->headers as $id => $caption) {
                
                $cellPos = sprintf('%s%s', $this->_getCellTag($index++), $startLine);
                
                // 设置比率行格式
                if (strpos($id, 'Ratio') !== false) {
                    
                    $style = $sheet->getStyle($cellPos[0]);
                    
                    $style->getNumberFormat()->setFormatCode(
                        \PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00
                    );
                    
                    $sheet->getColumnDimension($cellPos[0])->setAutoSize(true);
                }
                
                $sheet->setCellValue($cellPos, $row[$id]);
                
            }
            
        }
    }
    
    /**
     * 获取Excel列编号
     * 
     * @param int $cellNum 第几列
     * 
     * @return string
     */
    private function _getCellTag($cellNum)
    {
        $cellTag = '';
        if ($cellNum > 25) {
            $cellTag = $this->_letters[floor($cellNum / 26) - 1];
            $cellNum = ($cellNum % 26);
        }
        $cellTag .= $this->_letters[$cellNum];

        return $cellTag;
    }

    /**
     * 输出表
     *
     * @return void
     */
    public function output()
    {
        if ($this->table === null) {
            return;
        }
        
        // 设置表头
        $this->setHeaders();
        
        // 设置表内容
        $this->setContents();
        
        // 输出excel
        $filters = $this->table->getFilters();
        $filename = sprintf(
            '%s[%s].xls',
            $this->table->name,
            //$filters['startDate']->value,
            //$filters['endDate']->value
            $filters['date']->value
        );
        //解决IE下文件名乱码
        $filename = mb_convert_encoding($filename, 'gbk', 'utf-8');
        $writer = new \PHPExcel_Writer_Excel5($this->excel);
        header("Pragma: public");
        header("Expires: 0");
        header("Cache-Control:must-revalidate, post-check=0, pre-check=0");
        header("Content-Type:application/force-download");
        header("Content-Type:application/vnd.ms-execl");
        header("Content-Type:application/octet-stream");
        header("Content-Type:application/download");
        header('Content-Disposition:attachment;filename="' . $filename . '"');
        header("Content-Transfer-Encoding:binary");
        $writer->save('php://output');
    }
}


/**
 * 销售产品表Excel输出类
 *
 * @package   Ecga
 * @author    v.k <none@none.com>
 * @copyright 2010 Xingchangxinda Inc.
 * @version   Release: v0.1
 */
class ProductSalesExcelOutputer extends ExcelOutputer
{
  
    /**
     * 输出表内容
     *
     * @return void
     */
    protected function setContents()
    {
        $sheet = $this->excel->getActiveSheet();
        
        
        $startLine = 3; // headerGroups + headers
        $rowCount = 0; // sku总数量
        
        foreach ($this->table->rows as $model => $modelSkus) {
            
            $rowLine = $startLine - 1;
            
            // 输出sku内容
            foreach ($modelSkus['skus'] as $sku => $row) {
                
                $rowLine++;
                $sheet->setCellValue("A{$rowLine}", ' ' . $row['sku']);   
                $sheet->setCellValue("B{$rowLine}", $row['property']);
                $sheet->setCellValue("C{$rowLine}", $row['cateName']);
                $sheet->setCellValue("D{$rowLine}", $row['stockNum']);
                $sheet->setCellValue("E{$rowLine}", $row['totalOrderAmount']);
                $sheet->setCellValue("F{$rowLine}", $row['totalOrder']);
                $sheet->setCellValue("G{$rowLine}", $row['totalReturnNum']);
                $sheet->setCellValue("H{$rowLine}", $row['orderAmountRatio']);        
                $sheet->setCellValue("I{$rowLine}", $row['orderAmountRelativeRatio']);       
                //$sheet->setCellValue("H{$rowLine}", $row['stockCost']);       
                $sheet->setCellValue("J{$rowLine}", $row['stockDos']);
                // 设置SKU为字符串格式
                $skuCellPos = sprintf('%s3:%s%s', 'A', 'A', $rowCount);
                $sheet->getStyle($skuCellPos)->getNumberFormat()->setFormatCode(
                    \PHPExcel_Style_NumberFormat::FORMAT_TEXT
                );
                $rowCount++;
            }
            
            // 合并型号表格
            $rowSpan = count($modelSkus['skus']);
            for ($cell = 'K'; $cell <= 'R'; $cell++) {
                $mergeCells = sprintf(
                    '%s%s:%s%s', $cell, $startLine, $cell, $startLine + $rowSpan - 1
                );
                $sheet->mergeCells($mergeCells);
                // 设置文字居中
                $alignment = $sheet->getStyle($mergeCells)->getAlignment();
                $alignment->setVertical(
                    \PHPExcel_Style_Alignment::VERTICAL_CENTER
                );
            }
            
            // 输出型号内容
            $sheet->setCellValue("K{$startLine}", $modelSkus['model']);
            $sheet->setCellValue("L{$startLine}", $modelSkus['conversionRatio']);
            $sheet->setCellValue("M{$startLine}", $modelSkus['uv']);
            $sheet->setCellValue("N{$startLine}", $modelSkus['sumTotalOrderAmount']);
            $sheet->setCellValue("O{$startLine}", $modelSkus['sumTotalOrder']);
            $sheet->setCellValue("P{$startLine}", $modelSkus['sumOrderAmountRatio']);
            $sheet->setCellValue("Q{$startLine}", $modelSkus['sumOrderAmountRelativeRatio']);
            $sheet->setCellValue("R{$startLine}", $modelSkus['modelStockDos']);
            
            $startLine += $rowSpan;
        }
        
        // 设置百分比格式
        $percentages = array('H', 'I', 'L', 'P', 'Q');
        
        foreach ($percentages as $cell) {
            
            $cellPos = sprintf('%s3:%s%s', $cell, $cell, $rowCount);
            $sheet->getStyle($cellPos)->getNumberFormat()->setFormatCode(
                \PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00
            );
            
        }
        
    }
}